package chelydra.sharelydra.client;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.Map;
import org.jdesktop.application.Action;
import org.jdesktop.application.Application;
import org.jdesktop.application.SingleFrameApplication;

import chelydra.sharelydra.client.network.*;
import chelydra.sharelydra.client.ui.*;
import chelydra.sharelydra.client.webservice.*;
import chelydra.sharelydra.client.database.*;
import chelydra.sharelydra.client.file.FileManager;
import chelydra.sharelydra.client.friend.FriendManager;
import java.awt.event.ActionEvent;

/**
 *
 * @author Benjamin
 */
public class Core extends SingleFrameApplication {

	//Constant list;
	public static int VersionMessage = 1; //version of the protocol used
	public static int LocalPortClienttoClient = 1200; // local network port for client to client connection
	public static int FilePartMaxSize = 100000; //maximum file size for a slice of a file in byte

	//public static String Server = "http://localhost:8080/ShareLydra/";
	public static String Server = "http://poweredby.dyndns.org:8080/ShareLydra/";

	private DatabaseManager databaseManager;
	private FriendManager friendManager;
	private WebserviceManager webserviceManager;
	private MainView mainView;
	private Register registerView;

	/**
	 * At startup create and show the main frame of the application.
	 */
	@Override protected void startup() {
		// initialization of the different views and managers
		this.databaseManager = new DatabaseManager();
		this.friendManager = new FriendManager();
		this.webserviceManager = new WebserviceManager();
		this.webserviceManager.setServerURL(Server);
		this.mainView = new MainView(this);

		this.registerView = new Register(this.getMainFrame(), false);
		this.registerView.addWindowListener(new java.awt.event.WindowAdapter() {
			@Override
			public void windowClosing(java.awt.event.WindowEvent e) {
				System.exit(0);
			}
    });

		//the code below can't be modified
		//Start the different thread of the program
		try {
			InputSocket inSock = new InputSocket(LocalPortClienttoClient);
			inSock.start();
		} catch (IOException ex) {
			Logger.getLogger(Core.class.getName()).log(Level.SEVERE, null, ex);
		}


		// The code below can be modified
/*
		WebserviceManager m = new WebserviceManager("papy", "azerty");
	try {
		m.doConnect();
	} catch (WebserviceException ex) {
		Logger.getLogger(Core.class.getName()).log(Level.SEVERE, null, ex);
	}
*/

		/*String test= "tote est grand";
		try {
			DownloadFileThread dft = new DownloadFileThread(0, 65, "127.0.0.1", 1200,"toto.txt");
			dft.start();
		} catch (UnknownHostException ex) {
			Logger.getLogger(Core.class.getName()).log(Level.SEVERE, null, ex);
		} catch (IOException ex) {
			Logger.getLogger(Core.class.getName()).log(Level.SEVERE, null, ex);
		}*/

		this.initiateUser();        
	}

	/**
	 * Verifies if a user has already used the software and tries to use its information
	 * to connect to the service. Otherwise, shows the Register/Login view.
	 */
	protected void initiateUser() {
		Map<String,String> userInfos = this.databaseManager.existingUser();

		if (userInfos != null) {
			try {
				this.webserviceManager.setUserLogin(userInfos.get("UserLogin"));
				this.webserviceManager.setUserPassword(userInfos.get("UserPassword"));
				if (this.webserviceManager.doConnect(LocalPortClienttoClient)==null) {
					this.showView();
				} else {
					this.getDatabaseManager().eraseEmbeddedDatabase();
					show(this.getRegisterView());
				}
			} catch (WebserviceException ex) {
				ex.printStackTrace(System.err);
			}
		} else {
			this.getDatabaseManager().eraseEmbeddedDatabase();
			show(this.getRegisterView());
		}
	}

	/**
	 * Tries to login to the webserver using the username and login
	 * entered by user in the Register/Login View textfields.
	 * If login is successful, shows the main View.
	 * @param username Username entered by the user
	 * @param password password entered by user
	 * @return true if the webserver accepts our login, false otherwise
	 */
	public String tryToLogin(String username, String password) {
		String success = "An error occurred";

		try {
			this.webserviceManager.setUserLogin(username);
			this.webserviceManager.setUserPassword(password);

			this.getDatabaseManager().createEmbeddedDatabase();
			this.getDatabaseManager().setUserInformation("xxx", "xxx", username, password, "xxx", "xxx", "false", "false");

			success = this.webserviceManager.doConnect(LocalPortClienttoClient);

			if (success==null) {
				this.showView();
			}
		} catch (WebserviceException ex) {
			ex.printStackTrace(System.err);
		}
		
		return success;
	}

	/**
	 * Tries to register to the webserver using the information
	 * entered by user in the Register/Login View textfields.
	 * If login is successful, shows the main View.
	 * @param infos Map of the information entered in the textfields by user
	 * @return true if the webserver accepts our registering, false otherwise
	 */
	public String tryToRegister(Map<String,String> infos) {
		String success = "An error occurred";
		try {
			this.getDatabaseManager().createEmbeddedDatabase();
			this.getDatabaseManager().setUserInformation(infos.get("lastName"),
							infos.get("firstName"), infos.get("login"), infos.get("password"), 
							infos.get("email"), infos.get("nickname"), "false", "false");

			success = this.webserviceManager.doRegister(infos);

			if (success==null) {
				this.initiateUser();
			}
		} catch (WebserviceException ex) {
			ex.printStackTrace(System.err);
		}
		
		return success;
	}

	/**
	 * Shows the main view of the application, initiating the different tables
	 */
	public void showView() {
		show(this.getView());
		this.getView().updateNotifications();
		this.getView().updateGroupsTable();
		FileManager.FirstUpdateFileUI();
	}

	/**
	 * Action to disconnect the user.
	 * Disconnects from the server, and shows the login/register view.
	 */
	@Action
	public void disconnect() {
		try {
			this.webserviceManager.doDisconnect();
			this.hide(this.getView());
			this.getDatabaseManager().eraseEmbeddedDatabase();
			show(this.getRegisterView());
		} catch (WebserviceException ex) {
			ex.printStackTrace(System.err);
		}
	}
	
	/**
	 * This method is to initialize the specified window by injecting resources.
	 * Windows shown in our application come fully initialized from the GUI
	 * builder, so this additional configuration is not needed.
	 */
	@Override protected void configureWindow(java.awt.Window root) {
	}

	/**
	 * A convenient static getter for the application instance.
	 * @return the instance of Core
	 */
	public static Core getApplication() {
			return Application.getInstance(Core.class);
	}

	/**
	 * @param args the command line arguments
	 */
	public static void main(String[] args) {
		launch(Core.class, args);
	}
	
	// <editor-fold defaultstate="collapsed" desc="Getters/Setters">
	public DatabaseManager getDatabaseManager() {
		return databaseManager;
	}

	public MainView getView() {
		return mainView;
	}

	public Register getRegisterView() {
		return registerView;
	}

	public FriendManager getFriendManager() {
		return friendManager;
	}

	public WebserviceManager getWebserviceManager() {
		return webserviceManager;
	}
	// </editor-fold>

	@Action
	@Override
	public void quit(ActionEvent e) {
		try {
			System.err.println("AZERTY");
			this.webserviceManager.doDisconnect();
			this.databaseManager.shutdownDatabase();
		} catch (WebserviceException ex) {
			ex.printStackTrace(System.err);
		}
		this.exit();
	}

}
